package xin.pms.service;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xin.common.http.response.PageResponse;
import xin.common.http.response.PageWrapper;
import xin.common.utils.StringUtils;
import xin.core.ErrorConstant;
import xin.core.jpa.JpaConstant;
import xin.core.exception.SysException;
import xin.pms.model.User;
import xin.pms.repository.UserRepository;
import xin.pms.request.UserPageRequest;
import xin.pms.ui.AddUser;
import xin.pms.ui.UiUser;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <pre>
 * User Service
 * </pre>
 *
 * @author lixin_ma@outlook.com
 * @version 1.0
 * @since 2018/7/28 16:31
 */
@Service
@Transactional(readOnly = true)
@Slf4j
@CacheConfig(cacheNames = "userService")
public class UserService {

    @Autowired
    private UserRepository repository;

//    @Cacheable(value = "userIdCache",key = "#userId")
    public User findOne(String userId){
        return  repository.findOne(userId);
    }

    public User findByUserName(String userName){
        return repository.findByUserName(userName);
    }

    public PageResponse findPageList(UserPageRequest request ){
        Sort sort = new Sort(Sort.Direction.DESC,"lastModifyTime");
        Pageable pageable = new PageRequest(request.getPageNumber()-1,request.getPageSize(),sort);
        Specification<User> specification = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if(StringUtils.isNotBlank(request.getUserName())){
                predicates.add(criteriaBuilder.like(root.get("userName"),
                        JpaConstant.WILDCARD + request.getUserName() + JpaConstant.WILDCARD));
            }
            if(StringUtils.isNotBlank(request.getMobile())){
                predicates.add(criteriaBuilder.like(root.get("mobile"),
                        JpaConstant.WILDCARD + request.getMobile() + JpaConstant.WILDCARD));
            }
            if(StringUtils.isNotBlank(request.getName())){
                predicates.add(criteriaBuilder.like(root.get("name"),
                        JpaConstant.WILDCARD + request.getName() + JpaConstant.WILDCARD));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        return PageWrapper.wrap(repository.findAll(specification, pageable));
    }

    @Transactional
//    @CachePut(value = "userIdCache",key = "#userId")
    public User resetPasswd(String userId,String passwd){
        User user = repository.findOne(userId);
        String salt = BCrypt.gensalt();
        String passwdHash = BCrypt.hashpw(passwd, salt);
        user.setPasswordHash(passwdHash);
        user.setLastPasswordResetDate(new Date(System.currentTimeMillis()));
        return repository.save(user);
    }

    @Transactional
//    @CachePut(value = "userIdCache",key = "#userId")
    public User resetMobile(String userId,String mobile){
        User user = repository.findOne(userId);
        user.setMobile(mobile);
        return repository.save(user);
    }

    @Transactional
    public User update(UiUser ui) {
        User user = repository.findOne(ui.getId());
        if(user == null){
            throw new SysException(ErrorConstant.ERROR_DATA_0001,"修改用户不存在");
        }
        if(StringUtils.isNotBlank(ui.getName())){
            user.setName(ui.getName());
        }
        if(StringUtils.isNotBlank(ui.getWechat())){
            user.setWechat(ui.getWechat());
        }
        if(StringUtils.isNotBlank(ui.getMobile())){
            user.setMobile(ui.getMobile());
        }
        if(StringUtils.isNotBlank(ui.getMail())){
            user.setMail(ui.getMail());
        }
        if(StringUtils.isNotBlank(ui.getIdNum())){
            user.setIdNum(ui.getIdNum());
        }
        if(StringUtils.isNotBlank(ui.getIdType())){
            user.setIdType(ui.getIdType());
        }
        if(StringUtils.isNotBlank(ui.getCompany())){
            user.setCompany(ui.getCompany());
        }
        if(StringUtils.isNotBlank(ui.getDepartment())){
            user.setDepartment(ui.getDepartment());
        }
        user.setLastModifyTime(new Date(System.currentTimeMillis()));
        user.setDeleted(ui.isDeleted());
        user.setLocked(ui.isLocked());
        return repository.save(user);
    }

    @Transactional
    public User add(AddUser registUser) {
        /**
         * 校验用户是否重复
         */
        User user = repository.findByUserName(registUser.getUserName());
        if (user != null) {
            throw new SysException(ErrorConstant.SYS_REGIST,"用户名已存在");
        }
        user = repository.findByMobile(registUser.getMobile());
        if(user != null){
            throw new SysException(ErrorConstant.SYS_REGIST,"手机号已注册");
        }
        user = new User();
        user.setUserName(registUser.getUserName());
        user.setName(registUser.getName());
        user.setWechat(registUser.getWechat());
        user.setMobile(registUser.getMobile());
        user.setMail(registUser.getMail());
        user.setIdNum(registUser.getIdNum());
        user.setIdType(registUser.getIdType());
        user.setCompany(registUser.getCompany());
        user.setDepartment(registUser.getDepartment());
        user.setLastModifyTime(new Date(System.currentTimeMillis()));
        user.setCreateTime(new Date(System.currentTimeMillis()));
        user.setLastPasswordResetDate(new Date(System.currentTimeMillis()));
        user.setDeleted(Boolean.FALSE);
        user.setLocked(Boolean.FALSE);
        user.setLastModifyTime(new Date(System.currentTimeMillis()));

        String passwd = registUser.getPasswd();
        String salt = BCrypt.gensalt();
        String passwdHash = BCrypt.hashpw(passwd, salt);
        user.setPasswordHash(passwdHash);
        user.setLastPasswordResetDate(new Date(System.currentTimeMillis()));

        return repository.save(user);
    }

    @Transactional
    public void delete(String userId) {
        User user = repository.findOne(userId);
        if (user == null) {
            throw new SysException(ErrorConstant.ERROR_DATA_0001,"用户不存在");
        }
        repository.delete(userId);
    }
}
